Swift 属性
属性关联特定类、结构体或枚举的值。Swift主要有存储属性和计算属性。存储属性存储实例的常量或者变量值,然而计算属性主要是计算值(而不是存储值),相当于是附加属性,可以用已有的存储属性计算得到。
计算和存储属性同样一般是关联特定类型的实例。然而,属性同样能够和类型本身关联。这样的属性叫做类型属性。
此外,你还能够定义属性观察器来监视属性值的变化,利用它,你可以写一些响应的操作。属性观察器既能够自己定义,也能够从父类当中继承得到。
存储属性
存储属性,最简单的形式,就是存储在一个特定的类或机构体的实例中的,一个常量或变量。存储属性既可以是变量(由关键字var定义),也可以是常量(由关键字let定义)。
下面的例子,定义了一个结构FixedLengthRange,描述了一个整型数据的范围,其中的范围长度创建以后就不能改变。
1 |
|
常量结构体实例的存储属性
假如你创建了一个结构体实例,并将它赋给一个常量,那么你就不能改变这个实例的属性,包括变量属性,如下:
1 |
|
因为rangeOfFourItems被声明为一个常量,所以不可能改变它的firstValue属性,尽管它是一个变量属性。
这个行为是因为结构体属于值类型。值类型的实例如果标记为常量,那么它的所有属性都是常量。
这中情况对类并不适用,类是引用类型。假如你将一个引用类型的实例赋给一个常量,你仍然可以改变实例的变量属性。
懒(加载)存储属性
懒属性就是一种属性,直到它第一次被使用,它的值才会被计算。
注意点
懒属性必须声明为一个变量,因为它的初始值不会被用到,在实例初始化完成后。而常量属性必须在初始化完成以后有值,因此它不能被声明为懒属性
懒属性在以下情况下非常有用:它的值依赖于外在因素,也就是实例初始化完以后,这些外在因素还不知道的情况。还有就是,属性的值计算非常复杂或者计算代价非常高。只有使用它的时候去计算最好。
下面例子,利用懒存储属性,避免一个复杂类的不必要初始化。这个例子定义两个类DataImporter和DataManager:
1 |
|
DataManager类用来管理属性data, 一个String数组。
DataManager的部分功能是从文件当中获取data。然后这个功能是由类DataImporter提供的,需要花费相当多的时间进行初始化。这可能是因为DataImporter实例需要打开文件,将文件内容读入到内存等等。
但是使用了懒属性,使用lazy标记,importer属性对应的DataImporter实例,只有当importer属性第一次被使用的时候才会被创建,比方说它的文件名被访问的时候;1
2
3print(manager.importer.filename)
// the DataImporter instance for the importer property has now been created
// Prints "data.txt"
计算属性
除了存储属性,类,结构体和枚举也能够定义计算属性,它实际上不存储一个值。相反,它们提供一个获取和可选的设置,用来直接检索或设置属性和值。
1 |
|
这个例子定义来地理形状的三个结构:
Point封装了一个点的x-和y-坐标Size封装了长度和宽度Rect定义了一个长方形通过一个原点的点和尺寸
Rect结构同样提供了一个计算属性center。这个属性可以依赖orgin和size算出来,设置它,可以通过size,改变origin。也就是计算属性,主要是提供一些不是最原始的属性,但是又可以方便用户使用和设置的一种属性。
只读计算属性
计算属性只有获取(getter)就叫做只读计算属性。只读计算属性经常返回一个值,所以可用点的语法获取。
同样,可以用简写的形式,去掉get关键字和它的大括号:
1 |
|
属性观察器
属性观察器观察并对属性值的变化作出响应。属性观察器,在每一次属性值设置的时候都会被调用,即使新的属性值和现在的值一样。
你可以给任何存储属性添加属性观察器,除了懒加载存储属性。你也可以给任何继承的属性添加属性观察器,通过在子类中重写属性。
你可以针对一个属性,定义单个或者同时定义两个观察器。
willSet在值被存储前被调用disSet在新值存储后立即被调用
如果你实现一个willSet观察器,它会被传递新的属性值作为常量参数,并且你可以对这个人参数指定一个名字。如果你不指定名字,这个参数的默认名字为newValue。
类似的,如果你实现disSet观察器,它会被传递一个常量参数,包含的是先前的值。你同样可以为这个参数命名,或者使用默认值oldValue。
接下来,是一个willSet和disSet的例子。这个例子,是一个StepCounter的类,用来记步,它用一个变量totalSteps来记录当前的步数。
1 |
|
这个类用一个变量totalSteps来记录当前的步数。无论什么时候,只要属性被赋予新值,其中的willSet和disSet观察器都会被调用。willSet中,每次都会输出新的步数。而在didSet中,当新的步数超过旧的步数的时候,就输出新增多少步。
全局和局部变量
以上所描述的计算和观察属性对全局和局部变量都试用。全局变量定义在任何函数、方法、闭包或者类型上下文的外面。其它情况,都是局部变量。
类型属性
类型属性就是平常说的类属性,和类绑定,而和实例无关。
类属性,同样也可以是变量或者常量。计算类型属性同样也只能是变量,同一般的实例属性一样。
类型属性语法
定义类属性使用static关键字。对于需要继承的可计算类型属性,可以使用class关键字替代。下面是类属性的例子:
1 |
|